import { Entity } from "../../../../../Core/Module/Entity/Entity";
import { SceneType } from "../../../../../Core/Module/Entity/SceneType";
import { AwakeSystem, IAwake } from "../../../../../Core/Module/EventSystem/IAwakeSystem";
import { ILoad, LoadSystem } from "../../../../../Core/Module/EventSystem/ILoadSystem";
import { ExpandOf, FriendOf, ImplementsInterface, ObjectSystemAttribute } from "../../../../../Decorator/Decorator";
import { List } from "../../../../../Support/Share/Lib/Collections/List";
import { Dictionary } from "../../../../../Support/Share/Lib/Dictionary";
import { Unit } from "../Unit/Unit";
import { INumericWatcher } from "./INumericWatcher";
import { EventType } from "./NumericComponent";

export class NumericWatcherInfo {
    public SceneType: SceneType;
    public INumericWatcher: INumericWatcher;

    public NumericWatcherInfo(sceneType: SceneType, numericWatcher: INumericWatcher) {
        this.SceneType = sceneType;
        this.INumericWatcher = numericWatcher;
    }
}

@ImplementsInterface(IAwake)
@ImplementsInterface(ILoad)
export class NumericWatcherComponent extends Entity implements IAwake, ILoad {

    public static Instance: NumericWatcherComponent;

    public allWatchers: Dictionary<number, List<NumericWatcherInfo>>

}

/**
 * 使用 Expand 扩展方法
 * 
 * 必须作出以下申明，才能调用对象的扩展方法
 */
declare module "./NumericWatcherComponent" {

    interface NumericWatcherComponent {

        Init(): void;
        Run(unit: Unit, args: EventType.NumbericChange): void;
    }

}

@ExpandOf(NumericWatcherComponent)
export class NumericWatcherComponentSystem {

    private static Init(self: NumericWatcherComponent): void {
        self.allWatchers = new Dictionary<number, List<NumericWatcherInfo>>();

    }

    private static Run(self: NumericWatcherComponent, unit: Unit, args: EventType.NumbericChange): void {
        let list = self.allWatchers.TryGetValue(args.NumericType);
        if (!list) {
            return;
        }
        let unitDomainSceneType = unit.DomainScene().SceneType;
        for (let key in list) {
            let numericWatcher = list[key];
            if (numericWatcher.SceneType != unitDomainSceneType) {
                continue;
            }
            numericWatcher.INumericWatcher.Run(unit, args);
        }
    }

}

@FriendOf(NumericWatcherComponent)
@ObjectSystemAttribute()
export class NumericWatcherComponentAwakeSystem extends AwakeSystem<NumericWatcherComponent> {

    Awake(self: NumericWatcherComponent): void {
        NumericWatcherComponent.Instance = self;
        self.Init();
    }

}

@FriendOf(NumericWatcherComponent)
@ObjectSystemAttribute()
export class NumericWatcherComponentLoadSystem extends LoadSystem<NumericWatcherComponent> {

    Load(self: NumericWatcherComponent): void {
        self.Init();
    }

}